home *** CD-ROM | disk | FTP | other *** search
- Subject: v07i052: 2.11 News Source, Part02/09
- Newsgroups: mod.sources
- Approved: mirror!rs
-
- Submitted by: seismo!rick (Rick Adams)
- Mod.sources: Volume 7, Issue 52
- Archive-name: 2.11news/Part12
-
- # To extract, sh this file
- #
- # news 2.11 source part 2 of 9
- #
- if test ! -d src
- then
- mkdir src
- fi
- echo x - src/compress.c 1>&2
- sed 's/.//' >src/compress.c <<'*-*-END-of-src/compress.c-*-*'
- -#ifdef SCCSID
- -static char *SccsId = "@(#)compress.c 1.12 10/29/86";
- -#endif SCCSID
- -static char rcs_ident[] = "Based on compress.c,v 4.0 85/07/30 12:50:00 joe Release";
- -
- -/*
- - * Compress - data compression program
- - */
- -#define min(a,b) ((a>b) ? b : a)
- -
- -/*
- - * machine variants which require cc -Dmachine: pdp11, z8000, pcxt
- - */
- -
- -/*
- - * Set USERMEM to the maximum amount of physical user memory available
- - * in bytes. USERMEM is used to determine the maximum BITS that can be used
- - * for compression.
- - *
- - * SACREDMEM is the amount of physical memory saved for others; compress
- - * will hog the rest.
- - */
- -#ifndef SACREDMEM
- -#define SACREDMEM 0
- -#endif
- -
- -#ifndef USERMEM
- -# define USERMEM 450000 /* default user memory */
- -#endif
- -
- -#ifdef interdata /* (Perkin-Elmer) */
- -#define SIGNED_COMPARE_SLOW /* signed compare is slower than unsigned */
- -#endif
- -
- -#ifdef pdp11
- -# define BITS 12 /* max bits/code for 16-bit machine */
- -# define NO_UCHAR /* also if "unsigned char" functions as signed char */
- -# undef USERMEM
- -#endif /* pdp11 */ /* don't forget to compile with -i */
- -
- -#ifdef z8000
- -# define BITS 12
- -# undef vax /* weird preprocessor */
- -# undef USERMEM
- -#endif /* z8000 */
- -
- -#ifdef pcxt
- -# define BITS 12
- -# undef USERMEM
- -#endif /* pcxt */
- -
- -#ifdef USERMEM
- -# if USERMEM >= (433484+SACREDMEM)
- -# define PBITS 16
- -# else
- -# if USERMEM >= (229600+SACREDMEM)
- -# define PBITS 15
- -# else
- -# if USERMEM >= (127536+SACREDMEM)
- -# define PBITS 14
- -# else
- -# if USERMEM >= (73464+SACREDMEM)
- -# define PBITS 13
- -# else
- -# define PBITS 12
- -# endif
- -# endif
- -# endif
- -# endif
- -# undef USERMEM
- -#endif /* USERMEM */
- -
- -#ifdef PBITS /* Preferred BITS for this memory size */
- -# ifndef BITS
- -# define BITS PBITS
- -# endif BITS
- -#endif /* PBITS */
- -
- -#if BITS == 16
- -# define HSIZE 69001 /* 95% occupancy */
- -#endif
- -#if BITS == 15
- -# define HSIZE 35023 /* 94% occupancy */
- -#endif
- -#if BITS == 14
- -# define HSIZE 18013 /* 91% occupancy */
- -#endif
- -#if BITS == 13
- -# define HSIZE 9001 /* 91% occupancy */
- -#endif
- -#if BITS <= 12
- -# define HSIZE 5003 /* 80% occupancy */
- -#endif
- -
- -#ifdef M_XENIX /* Stupid compiler can't handle arrays with */
- -# if BITS == 16 /* more than 65535 bytes - so we fake it */
- -# define XENIX_16
- -# else
- -# if BITS > 13 /* Code only handles BITS = 12, 13, or 16 */
- -# define BITS 13
- -# endif
- -# endif
- -#endif
- -
- -/*
- - * a code_int must be able to hold 2**BITS values of type int, and also -1
- - */
- -#if BITS > 15
- -typedef long int code_int;
- -#else
- -typedef int code_int;
- -#endif
- -
- -#ifdef SIGNED_COMPARE_SLOW
- -typedef unsigned long int count_int;
- -typedef unsigned short int count_short;
- -#else
- -typedef long int count_int;
- -#endif
- -
- -#ifdef NO_UCHAR
- - typedef char char_type;
- -#else
- - typedef unsigned char char_type;
- -#endif /* UCHAR */
- -char_type magic_header[] = { "\037\235" }; /* 1F 9D */
- -
- -/* Defines for third byte of header */
- -#define BIT_MASK 0x1f
- -#define BLOCK_MASK 0x80
- -/* Masks 0x40 and 0x20 are free. I think 0x20 should mean that there is
- - a fourth header byte (for expansion).
- -*/
- -#define INIT_BITS 9 /* initial number of bits/code */
- -
- -/*
- - * compress.c - File compression ala IEEE Computer, June 1984.
- - *
- - * Authors: Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas)
- - * Jim McKie (decvax!mcvax!jim)
- - * Steve Davies (decvax!vax135!petsd!peora!srd)
- - * Ken Turkowski (decvax!decwrl!turtlevax!ken)
- - * James A. Woods (decvax!ihnp4!ames!jaw)
- - * Joe Orost (decvax!vax135!petsd!joe)
- - *
- - */
- -
- -#include <stdio.h>
- -#include <ctype.h>
- -#include <signal.h>
- -#include <sys/types.h>
- -#include <sys/stat.h>
- -
- -#define ARGVAL() (*++(*argv) || (--argc && *++argv))
- -
- -int n_bits; /* number of bits/code */
- -int maxbits = BITS; /* user settable max # bits/code */
- -code_int maxcode; /* maximum code, given n_bits */
- -code_int maxmaxcode = 1L << BITS; /* should NEVER generate this code */
- -#ifdef COMPATIBLE /* But wrong! */
- -# define MAXCODE(n_bits) (1 << (n_bits) - 1)
- -#else
- -# define MAXCODE(n_bits) ((1 << (n_bits)) - 1)
- -#endif /* COMPATIBLE */
- -
- -#ifdef XENIX_16
- -count_int htab0[8192];
- -count_int htab1[8192];
- -count_int htab2[8192];
- -count_int htab3[8192];
- -count_int htab4[8192];
- -count_int htab5[8192];
- -count_int htab6[8192];
- -count_int htab7[8192];
- -count_int htab8[HSIZE-65536];
- -count_int * htab[9] = {
- - htab0, htab1, htab2, htab3, htab4, htab5, htab6, htab7, htab8 };
- -
- -#define htabof(i) (htab[(i) >> 13][(i) & 0x1fff])
- -unsigned short code0tab[16384];
- -unsigned short code1tab[16384];
- -unsigned short code2tab[16384];
- -unsigned short code3tab[16384];
- -unsigned short code4tab[16384];
- -unsigned short * codetab[5] = {
- - code0tab, code1tab, code2tab, code3tab, code4tab };
- -
- -#define codetabof(i) (codetab[(i) >> 14][(i) & 0x3fff])
- -
- -#else /* Normal machine */
- -# ifdef sel
- -/* support gould base register problems */
- -/*NOBASE*/
- -count_int htab [HSIZE];
- -unsigned short codetab [HSIZE];
- -/*NOBASE*/
- -# else /* !gould */
- -count_int htab [HSIZE];
- -unsigned short codetab [HSIZE];
- -# endif /* !gould */
- -#define htabof(i) htab[i]
- -#define codetabof(i) codetab[i]
- -#endif /* !XENIX_16 */
- -code_int hsize = HSIZE; /* for dynamic table sizing */
- -count_int fsize;
- -
- -/*
- - * To save much memory, we overlay the table used by compress() with those
- - * used by decompress(). The tab_prefix table is the same size and type
- - * as the codetab. The tab_suffix table needs 2**BITS characters. We
- - * get this from the beginning of htab. The output stack uses the rest
- - * of htab, and contains characters. There is plenty of room for any
- - * possible stack (stack used to be 8000 characters).
- - */
- -
- -#define tab_prefixof(i) codetabof(i)
- -#ifdef XENIX_16
- -# define tab_suffixof(i) ((char_type *)htab[(i)>>15])[(i) & 0x7fff]
- -# define de_stack ((char_type *)(htab2))
- -#else /* Normal machine */
- -# define tab_suffixof(i) ((char_type *)(htab))[i]
- -# define de_stack ((char_type *)&tab_suffixof(1<<BITS))
- -#endif /* XENIX_16 */
- -
- -code_int free_ent = 0; /* first unused entry */
- -int exit_stat = 0;
- -
- -code_int getcode();
- -
- -Usage() {
- -#ifdef DEBUG
- -fprintf(stderr,"Usage: compress [-dDVfc] [-b maxbits] [file ...]\n");
- -}
- -int debug = 0;
- -#else
- -fprintf(stderr,"Usage: compress [-dfvcV] [-b maxbits] [file ...]\n");
- -}
- -#endif /* DEBUG */
- -int nomagic = 0; /* Use a 3-byte magic number header, unless old file */
- -int zcat_flg = 0; /* Write output on stdout, suppress messages */
- -int quiet = 1; /* don't tell me about compression */
- -
- -/*
- - * block compression parameters -- after all codes are used up,
- - * and compression rate changes, start over.
- - */
- -int block_compress = BLOCK_MASK;
- -int clear_flg = 0;
- -long int ratio = 0;
- -#define CHECK_GAP 10000 /* ratio check interval */
- -count_int checkpoint = CHECK_GAP;
- -/*
- - * the next two codes should not be changed lightly, as they must not
- - * lie within the contiguous general code space.
- - */
- -#define FIRST 257 /* first free entry */
- -#define CLEAR 256 /* table clear output code */
- -
- -int force = 0;
- -char ofname [100];
- -#ifdef DEBUG
- -int verbose = 0;
- -#endif /* DEBUG */
- -int (*bgnd_flag)();
- -
- -int do_decomp = 0;
- -
- -/*****************************************************************
- - * TAG( main )
- - *
- - * Algorithm from "A Technique for High Performance Data Compression",
- - * Terry A. Welch, IEEE Computer Vol 17, No 6 (June 1984), pp 8-19.
- - *
- - * Usage: compress [-dfvc] [-b bits] [file ...]
- - * Inputs:
- - * -d: If given, decompression is done instead.
- - *
- - * -c: Write output on stdout, don't remove original.
- - *
- - * -b: Parameter limits the max number of bits/code.
- - *
- - * -f: Forces output file to be generated, even if one already
- - * exists, and even if no space is saved by compressing.
- - * If -f is not used, the user will be prompted if stdin is
- - * a tty, otherwise, the output file will not be overwritten.
- - *
- - * -v: Write compression statistics
- - *
- - * file ...: Files to be compressed. If none specified, stdin
- - * is used.
- - * Outputs:
- - * file.Z: Compressed form of file with same mode, owner, and utimes
- - * or stdout (if stdin used as input)
- - *
- - * Assumptions:
- - * When filenames are given, replaces with the compressed version
- - * (.Z suffix) only if the file decreases in size.
- - * Algorithm:
- - * Modified Lempel-Ziv method (LZW). Basically finds common
- - * substrings and replaces them with a variable size code. This is
- - * deterministic, and can be done on the fly. Thus, the decompression
- - * procedure needs no input table, but tracks the way the table was built.
- - */
- -
- -main( argc, argv )
- -register int argc; char **argv;
- -{
- - int overwrite = 0; /* Do not overwrite unless given -f flag */
- - char tempname[100];
- - char **filelist, **fileptr;
- - char *cp, *rindex(), *malloc();
- - struct stat statbuf;
- - extern onintr(), oops();
- -
- -
- - if ( (bgnd_flag = signal ( SIGINT, SIG_IGN )) != SIG_IGN ) {
- - signal ( SIGINT, onintr );
- - signal ( SIGSEGV, oops );
- - }
- -
- -#ifdef COMPATIBLE
- - nomagic = 1; /* Original didn't have a magic number */
- -#endif /* COMPATIBLE */
- -
- - filelist = fileptr = (char **)(malloc(argc * sizeof(*argv)));
- - *filelist = NULL;
- -
- - if((cp = rindex(argv[0], '/')) != 0) {
- - cp++;
- - } else {
- - cp = argv[0];
- - }
- - if(strcmp(cp, "uncompress") == 0) {
- - do_decomp = 1;
- - } else if(strcmp(cp, "zcat") == 0) {
- - do_decomp = 1;
- - zcat_flg = 1;
- - }
- -
- -#ifdef BSD4_2
- - /* 4.2BSD dependent - take it out if not */
- - setlinebuf( stderr );
- -#endif /* BSD4_2 */
- -
- - /* Argument Processing
- - * All flags are optional.
- - * -D => debug
- - * -V => print Version; debug verbose
- - * -d => do_decomp
- - * -v => unquiet
- - * -f => force overwrite of output file
- - * -n => no header: useful to uncompress old files
- - * -b maxbits => maxbits. If -b is specified, then maxbits MUST be
- - * given also.
- - * -c => cat all output to stdout
- - * -C => generate output compatible with compress 2.0.
- - * if a string is left, must be an input filename.
- - */
- - for (argc--, argv++; argc > 0; argc--, argv++) {
- - if (**argv == '-') { /* A flag argument */
- - while (*++(*argv)) { /* Process all flags in this arg */
- - switch (**argv) {
- -#ifdef DEBUG
- - case 'D':
- - debug = 1;
- - break;
- - case 'V':
- - verbose = 1;
- - version();
- - break;
- -#else
- - case 'V':
- - version();
- - break;
- -#endif /* DEBUG */
- - case 'v':
- - quiet = 0;
- - break;
- - case 'd':
- - do_decomp = 1;
- - break;
- - case 'f':
- - case 'F':
- - overwrite = 1;
- - force = 1;
- - break;
- - case 'n':
- - nomagic = 1;
- - break;
- - case 'C':
- - block_compress = 0;
- - break;
- - case 'b':
- - if (!ARGVAL()) {
- - fprintf(stderr, "Missing maxbits\n");
- - Usage();
- - exit(1);
- - }
- - maxbits = atoi(*argv);
- - goto nextarg;
- - case 'c':
- - zcat_flg = 1;
- - break;
- - case 'q':
- - quiet = 1;
- - break;
- - default:
- - fprintf(stderr, "Unknown flag: '%c'; ", **argv);
- - Usage();
- - exit(1);
- - }
- - }
- - }
- - else { /* Input file name */
- - *fileptr++ = *argv; /* Build input file list */
- - *fileptr = NULL;
- - /* process nextarg; */
- - }
- - nextarg: continue;
- - }
- -
- - if(maxbits < INIT_BITS) maxbits = INIT_BITS;
- - if (maxbits > BITS) maxbits = BITS;
- - maxmaxcode = 1L << maxbits;
- -
- - if (*filelist != NULL) {
- - for (fileptr = filelist; *fileptr; fileptr++) {
- - exit_stat = 0;
- - if (do_decomp != 0) { /* DECOMPRESSION */
- - /* Check for .Z suffix */
- - if (strcmp(*fileptr + strlen(*fileptr) - 2, ".Z") != 0) {
- - /* No .Z: tack one on */
- - strcpy(tempname, *fileptr);
- - strcat(tempname, ".Z");
- - *fileptr = tempname;
- - }
- - /* Open input file */
- - if ((freopen(*fileptr, "r", stdin)) == NULL) {
- - perror(*fileptr); continue;
- - }
- - /* Check the magic number */
- - if (nomagic == 0) {
- - if ((getchar() != (magic_header[0] & 0xFF))
- - || (getchar() != (magic_header[1] & 0xFF))) {
- - fprintf(stderr, "%s: not in compressed format\n",
- - *fileptr);
- - continue;
- - }
- - maxbits = getchar(); /* set -b from file */
- - block_compress = maxbits & BLOCK_MASK;
- - maxbits &= BIT_MASK;
- - maxmaxcode = 1L << maxbits;
- - if(maxbits > BITS) {
- - fprintf(stderr,
- - "%s: compressed with %d bits, can only handle %d bits\n",
- - *fileptr, maxbits, BITS);
- - continue;
- - }
- - }
- - /* Generate output filename */
- - strcpy(ofname, *fileptr);
- - ofname[strlen(*fileptr) - 2] = '\0'; /* Strip off .Z */
- - } else { /* COMPRESSION */
- - if (strcmp(*fileptr + strlen(*fileptr) - 2, ".Z") == 0) {
- - fprintf(stderr, "%s: already has .Z suffix -- no change\n",
- - *fileptr);
- - continue;
- - }
- - /* Open input file */
- - if ((freopen(*fileptr, "r", stdin)) == NULL) {
- - perror(*fileptr); continue;
- - }
- - stat ( *fileptr, &statbuf );
- - fsize = (long) statbuf.st_size;
- - /*
- - * tune hash table size for small files -- ad hoc,
- - * but the sizes match earlier #defines, which
- - * serve as upper bounds on the number of output codes.
- - */
- - hsize = HSIZE;
- - if ( fsize < (1 << 12) )
- - hsize = min ( 5003, HSIZE );
- - else if ( fsize < (1 << 13) )
- - hsize = min ( 9001, HSIZE );
- - else if ( fsize < (1 << 14) )
- - hsize = min ( 18013, HSIZE );
- - else if ( fsize < (1 << 15) )
- - hsize = min ( 35023, HSIZE );
- - else if ( fsize < 47000 )
- - hsize = min ( 50021, HSIZE );
- -
- - /* Generate output filename */
- - strcpy(ofname, *fileptr);
- -#ifndef BSD4_2 /* Short filenames */
- - if ((cp=rindex(ofname,'/')) != NULL) cp++;
- - else cp = ofname;
- - if (strlen(cp) > 12) {
- - fprintf(stderr,"%s: filename too long to tack on .Z\n",cp);
- - continue;
- - }
- -#endif /* BSD4_2 Long filenames allowed */
- - strcat(ofname, ".Z");
- - }
- - /* Check for overwrite of existing file */
- - if (overwrite == 0 && zcat_flg == 0) {
- - if (stat(ofname, &statbuf) == 0) {
- - char response[2];
- - response[0] = 'n';
- - fprintf(stderr, "%s already exists;", ofname);
- - if (foreground()) {
- - fprintf(stderr, " do you wish to overwrite %s (y or n)? ",
- - ofname);
- - fflush(stderr);
- - read(2, response, 2);
- - while (response[1] != '\n') {
- - if (read(2, response+1, 1) < 0) { /* Ack! */
- - perror("stderr"); break;
- - }
- - }
- - }
- - if (response[0] != 'y') {
- - fprintf(stderr, "\tnot overwritten\n");
- - continue;
- - }
- - }
- - }
- - if(zcat_flg == 0) { /* Open output file */
- - if (freopen(ofname, "w", stdout) == NULL) {
- - perror(ofname);
- - continue;
- - }
- - if(!quiet)
- - fprintf(stderr, "%s: ", *fileptr);
- - }
- -
- - /* Actually do the compression/decompression */
- - if (do_decomp == 0) compress();
- -#ifndef DEBUG
- - else decompress();
- -#else
- - else if (debug == 0) decompress();
- - else printcodes();
- - if (verbose) dump_tab();
- -#endif /* DEBUG */
- - if(zcat_flg == 0) {
- - copystat(*fileptr, ofname); /* Copy stats */
- - if((exit_stat == 1) || (!quiet))
- - putc('\n', stderr);
- - }
- - }
- - } else { /* Standard input */
- - if (do_decomp == 0) {
- - compress();
- -#ifdef DEBUG
- - if(verbose) dump_tab();
- -#endif /* DEBUG */
- - if(!quiet)
- - putc('\n', stderr);
- - } else {
- - /* Check the magic number */
- - if (nomagic == 0) {
- - if ((getchar()!=(magic_header[0] & 0xFF))
- - || (getchar()!=(magic_header[1] & 0xFF))) {
- - fprintf(stderr, "stdin: not in compressed format\n");
- - exit(1);
- - }
- - maxbits = getchar(); /* set -b from file */
- - block_compress = maxbits & BLOCK_MASK;
- - maxbits &= BIT_MASK;
- - maxmaxcode = 1L << maxbits;
- - fsize = 100000; /* assume stdin large for USERMEM */
- - if(maxbits > BITS) {
- - fprintf(stderr,
- - "stdin: compressed with %d bits, can only handle %d bits\n",
- - maxbits, BITS);
- - exit(1);
- - }
- - }
- -#ifndef DEBUG
- - decompress();
- -#else
- - if (debug == 0) decompress();
- - else printcodes();
- - if (verbose) dump_tab();
- -#endif /* DEBUG */
- - }
- - }
- - exit(exit_stat);
- -}
- -
- -static int offset;
- -long int in_count = 1; /* length of input */
- -long int bytes_out; /* length of compressed output */
- -long int out_count = 0; /* # of codes output (for debugging) */
- -
- -/*
- - * compress stdin to stdout
- - *
- - * Algorithm: use open addressing double hashing (no chaining) on the
- - * prefix code / next character combination. We do a variant of Knuth's
- - * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
- - * secondary probe. Here, the modular division first probe is gives way
- - * to a faster exclusive-or manipulation. Also do block compression with
- - * an adaptive reset, whereby the code table is cleared when the compression
- - * ratio decreases, but after the table fills. The variable-length output
- - * codes are re-sized at this point, and a special CLEAR code is generated
- - * for the decompressor. Late addition: construct the table according to
- - * file size for noticeable speed improvement on small files. Please direct
- - * questions about this implementation to ames!jaw.
- - */
- -
- -compress() {
- - register long fcode;
- - register code_int i = 0;
- - register int c;
- - register code_int ent;
- -#ifdef XENIX_16
- - register code_int disp;
- -#else /* Normal machine */
- - register int disp;
- -#endif
- - register code_int hsize_reg;
- - register int hshift;
- -
- -#ifndef COMPATIBLE
- - if (nomagic == 0) {
- - putchar(magic_header[0]); putchar(magic_header[1]);
- - putchar((char)(maxbits | block_compress));
- - if(ferror(stdout))
- - writeerr();
- - }
- -#endif /* COMPATIBLE */
- -
- - offset = 0;
- - bytes_out = 3; /* includes 3-byte header mojo */
- - out_count = 0;
- - clear_flg = 0;
- - ratio = 0;
- - in_count = 1;
- - checkpoint = CHECK_GAP;
- - maxcode = MAXCODE(n_bits = INIT_BITS);
- - free_ent = ((block_compress) ? FIRST : 256 );
- -
- - ent = getchar ();
- -
- - hshift = 0;
- - for ( fcode = (long) hsize; fcode < 65536L; fcode *= 2L )
- - hshift++;
- - hshift = 8 - hshift; /* set hash code range bound */
- -
- - hsize_reg = hsize;
- - cl_hash( (count_int) hsize_reg); /* clear hash table */
- -
- -#ifdef SIGNED_COMPARE_SLOW
- - while ( (c = getchar()) != (unsigned) EOF ) {
- -#else
- - while ( (c = getchar()) != EOF ) {
- -#endif
- - in_count++;
- - fcode = (long) (((long) c << maxbits) + ent);
- - i = (((long)c << hshift) ^ ent); /* xor hashing */
- -
- - if ( htabof (i) == fcode ) {
- - ent = codetabof (i);
- - continue;
- - } else if ( (long)htabof (i) < 0 ) /* empty slot */
- - goto nomatch;
- - disp = hsize_reg - i; /* secondary hash (after G. Knott) */
- - if ( i == 0 )
- - disp = 1;
- -probe:
- - if ( (i -= disp) < 0 )
- - i += hsize_reg;
- -
- - if ( htabof (i) == fcode ) {
- - ent = codetabof (i);
- - continue;
- - }
- - if ( (long)htabof (i) > 0 )
- - goto probe;
- -nomatch:
- - output ( (code_int) ent );
- - out_count++;
- - ent = c;
- -#ifdef SIGNED_COMPARE_SLOW
- - if ( (unsigned) free_ent < (unsigned) maxmaxcode) {
- -#else
- - if ( free_ent < maxmaxcode ) {
- -#endif
- - codetabof (i) = free_ent++; /* code -> hashtable */
- - htabof (i) = fcode;
- - }
- - else if ( (count_int)in_count >= checkpoint && block_compress )
- - cl_block ();
- - }
- - /*
- - * Put out the final code.
- - */
- - output( (code_int)ent );
- - out_count++;
- - output( (code_int)-1 );
- -
- - /*
- - * Print out stats on stderr
- - */
- - if(zcat_flg == 0 && !quiet) {
- -#ifdef DEBUG
- - fprintf( stderr,
- - "%ld chars in, %ld codes (%ld bytes) out, compression factor: ",
- - in_count, out_count, bytes_out );
- - prratio( stderr, in_count, bytes_out );
- - fprintf( stderr, "\n");
- - fprintf( stderr, "\tCompression as in compact: " );
- - prratio( stderr, in_count-bytes_out, in_count );
- - fprintf( stderr, "\n");
- - fprintf( stderr, "\tLargest code (of last block) was %d (%d bits)\n",
- - free_ent - 1, n_bits );
- -#else /* !DEBUG */
- - fprintf( stderr, "Compression: " );
- - prratio( stderr, in_count-bytes_out, in_count );
- -#endif /* DEBUG */
- - }
- - if(bytes_out > in_count) /* exit(2) if no savings */
- - exit_stat = 2;
- - return;
- -}
- -
- -/*****************************************************************
- - * TAG( output )
- - *
- - * Output the given code.
- - * Inputs:
- - * code: A n_bits-bit integer. If == -1, then EOF. This assumes
- - * that n_bits =< (long)wordsize - 1.
- - * Outputs:
- - * Outputs code to the file.
- - * Assumptions:
- - * Chars are 8 bits long.
- - * Algorithm:
- - * Maintain a BITS character long buffer (so that 8 codes will
- - * fit in it exactly). Use the VAX insv instruction to insert each
- - * code in turn. When the buffer fills up empty it and start over.
- - */
- -
- -static char buf[BITS];
- -
- -#ifndef vax
- -char_type lmask[9] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};
- -char_type rmask[9] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
- -#endif /* vax */
- -
- -output( code )
- -code_int code;
- -{
- -#ifdef DEBUG
- - static int col = 0;
- -#endif /* DEBUG */
- -
- - /*
- - * On the VAX, it is important to have the register declarations
- - * in exactly the order given, or the asm will break.
- - */
- - register int r_off = offset, bits= n_bits;
- - register char * bp = buf;
- -
- -#ifdef DEBUG
- - if ( verbose )
- - fprintf( stderr, "%5d%c", code,
- - (col+=6) >= 74 ? (col = 0, '\n') : ' ' );
- -#endif /* DEBUG */
- - if ( code >= 0 ) {
- -#ifdef vax
- - /* VAX DEPENDENT!! Implementation on other machines is below.
- - *
- - * Translation: Insert BITS bits from the argument starting at
- - * offset bits from the beginning of buf.
- - */
- - 0; /* Work around for pcc -O bug with asm and if stmt */
- - asm( "insv 4(ap),r11,r10,(r9)" );
- -#else /* not a vax */
- -/*
- - * byte/bit numbering on the VAX is simulated by the following code
- - */
- - /*
- - * Get to the first byte.
- - */
- - bp += (r_off >> 3);
- - r_off &= 7;
- - /*
- - * Since code is always >= 8 bits, only need to mask the first
- - * hunk on the left.
- - */
- - *bp = (*bp & rmask[r_off]) | (code << r_off) & lmask[r_off];
- - bp++;
- - bits -= (8 - r_off);
- - code >>= 8 - r_off;
- - /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
- - if ( bits >= 8 ) {
- - *bp++ = code;
- - code >>= 8;
- - bits -= 8;
- - }
- - /* Last bits. */
- - if(bits)
- - *bp = code;
- -#endif /* vax */
- - offset += n_bits;
- - if ( offset == (n_bits << 3) ) {
- - bp = buf;
- - bits = n_bits;
- - bytes_out += bits;
- - do
- - putchar(*bp++);
- - while(--bits);
- - offset = 0;
- - }
- -
- - /*
- - * If the next entry is going to be too big for the code size,
- - * then increase it, if possible.
- - */
- - if ( free_ent > maxcode || (clear_flg > 0))
- - {
- - /*
- - * Write the whole buffer, because the input side won't
- - * discover the size increase until after it has read it.
- - */
- - if ( offset > 0 ) {
- - if( fwrite( buf, 1, n_bits, stdout ) != n_bits)
- - writeerr();
- - bytes_out += n_bits;
- - }
- - offset = 0;
- -
- - if ( clear_flg ) {
- - maxcode = MAXCODE (n_bits = INIT_BITS);
- - clear_flg = 0;
- - }
- - else {
- - n_bits++;
- - if ( n_bits == maxbits )
- - maxcode = maxmaxcode;
- - else
- - maxcode = MAXCODE(n_bits);
- - }
- -#ifdef DEBUG
- - if ( debug ) {
- - fprintf( stderr, "\nChange to %d bits\n", n_bits );
- - col = 0;
- - }
- -#endif /* DEBUG */
- - }
- - } else {
- - /*
- - * At EOF, write the rest of the buffer.
- - */
- - if ( offset > 0 )
- - fwrite( buf, 1, (offset + 7) / 8, stdout );
- - bytes_out += (offset + 7) / 8;
- - offset = 0;
- - fflush( stdout );
- -#ifdef DEBUG
- - if ( verbose )
- - fprintf( stderr, "\n" );
- -#endif /* DEBUG */
- - if( ferror( stdout ) )
- - writeerr();
- - }
- -}
- -
- -/*
- - * Decompress stdin to stdout. This routine adapts to the codes in the
- - * file building the "string" table on-the-fly; requiring no table to
- - * be stored in the compressed file. The tables used herein are shared
- - * with those of the compress() routine. See the definitions above.
- - */
- -
- -decompress() {
- - register char_type *stackp;
- - register int finchar;
- - register code_int code, oldcode, incode;
- -
- - /*
- - * As above, initialize the first 256 entries in the table.
- - */
- - maxcode = MAXCODE(n_bits = INIT_BITS);
- - for ( code = 255; code >= 0; code-- ) {
- - tab_prefixof(code) = 0;
- - tab_suffixof(code) = (char_type)code;
- - }
- - free_ent = ((block_compress) ? FIRST : 256 );
- -
- - finchar = oldcode = getcode();
- - if(oldcode == -1) /* EOF already? */
- - return; /* Get out of here */
- - putchar( (char)finchar ); /* first code must be 8 bits = char */
- - if(ferror(stdout)) /* Crash if can't write */
- - writeerr();
- - stackp = de_stack;
- -
- - while ( (code = getcode()) > -1 ) {
- -
- - if ( (code == CLEAR) && block_compress ) {
- - for ( code = 255; code >= 0; code-- )
- - tab_prefixof(code) = 0;
- - clear_flg = 1;
- - free_ent = FIRST - 1;
- - if ( (code = getcode ()) == -1 ) /* O, untimely death! */
- - break;
- - }
- - incode = code;
- - /*
- - * Special case for KwKwK string.
- - */
- - if ( code >= free_ent ) {
- - *stackp++ = finchar;
- - code = oldcode;
- - }
- -
- - /*
- - * Generate output characters in reverse order
- - */
- -#ifdef SIGNED_COMPARE_SLOW
- - while ( ((unsigned long)code) >= ((unsigned long)256) ) {
- -#else
- - while ( code >= 256 ) {
- -#endif
- - *stackp++ = tab_suffixof(code);
- - code = tab_prefixof(code);
- - }
- - *stackp++ = finchar = tab_suffixof(code);
- -
- - /*
- - * And put them out in forward order
- - */
- - do
- - putchar ( *--stackp );
- - while ( stackp > de_stack );
- -
- - /*
- - * Generate the new entry.
- - */
- - if ( (code=free_ent) < maxmaxcode ) {
- - tab_prefixof(code) = (unsigned short)oldcode;
- - tab_suffixof(code) = finchar;
- - free_ent = code+1;
- - }
- - /*
- - * Remember previous code.
- - */
- - oldcode = incode;
- - }
- - fflush( stdout );
- - if(ferror(stdout))
- - writeerr();
- -}
- -
- -/*****************************************************************
- - * TAG( getcode )
- - *
- - * Read one code from the standard input. If EOF, return -1.
- - * Inputs:
- - * stdin
- - * Outputs:
- - * code or -1 is returned.
- - */
- -
- -code_int
- -getcode() {
- - /*
- - * On the VAX, it is important to have the register declarations
- - * in exactly the order given, or the asm will break.
- - */
- - register code_int code;
- - static int offset = 0, size = 0;
- - static char_type buf[BITS];
- - register int r_off, bits;
- - register char_type *bp = buf;
- -
- - if ( clear_flg > 0 || offset >= size || free_ent > maxcode ) {
- - /*
- - * If the next entry will be too big for the current code
- - * size, then we must increase the size. This implies reading
- - * a new buffer full, too.
- - */
- - if ( free_ent > maxcode ) {
- - n_bits++;
- - if ( n_bits == maxbits )
- - maxcode = maxmaxcode; /* won't get any bigger now */
- - else
- - maxcode = MAXCODE(n_bits);
- - }
- - if ( clear_flg > 0) {
- - maxcode = MAXCODE (n_bits = INIT_BITS);
- - clear_flg = 0;
- - }
- - size = fread( buf, 1, n_bits, stdin );
- - if ( size <= 0 )
- - return -1; /* end of file */
- - offset = 0;
- - /* Round size down to integral number of codes */
- - size = (size << 3) - (n_bits - 1);
- - }
- - r_off = offset;
- - bits = n_bits;
- -#ifdef vax
- - asm( "extzv r10,r9,(r8),r11" );
- -#else /* not a vax */
- - /*
- - * Get to the first byte.
- - */
- - bp += (r_off >> 3);
- - r_off &= 7;
- - /* Get first part (low order bits) */
- -#ifdef NO_UCHAR
- - code = ((*bp++ >> r_off) & rmask[8 - r_off]) & 0xff;
- -#else
- - code = (*bp++ >> r_off);
- -#endif /* NO_UCHAR */
- - bits -= (8 - r_off);
- - r_off = 8 - r_off; /* now, offset into code word */
- - /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
- - if ( bits >= 8 ) {
- -#ifdef NO_UCHAR
- - code |= (*bp++ & 0xff) << r_off;
- -#else
- - code |= *bp++ << r_off;
- -#endif /* NO_UCHAR */
- - r_off += 8;
- - bits -= 8;
- - }
- - /* high order bits. */
- - code |= (*bp & rmask[bits]) << r_off;
- -#endif /* vax */
- - offset += n_bits;
- -
- - return code;
- -}
- -
- -char *
- -rindex(s, c) /* For those who don't have it in libc.a */
- -register char *s, c;
- -{
- - char *p;
- - for (p = NULL; *s; s++)
- - if (*s == c)
- - p = s;
- - return(p);
- -}
- -
- -#ifdef DEBUG
- -printcodes()
- -{
- - /*
- - * Just print out codes from input file. For debugging.
- - */
- - code_int code;
- - int col = 0, bits;
- -
- - bits = n_bits = INIT_BITS;
- - maxcode = MAXCODE(n_bits);
- - free_ent = ((block_compress) ? FIRST : 256 );
- - while ( ( code = getcode() ) >= 0 ) {
- - if ( (code == CLEAR) && block_compress ) {
- - free_ent = FIRST - 1;
- - clear_flg = 1;
- - }
- - else if ( free_ent < maxmaxcode )
- - free_ent++;
- - if ( bits != n_bits ) {
- - fprintf(stderr, "\nChange to %d bits\n", n_bits );
- - bits = n_bits;
- - col = 0;
- - }
- - fprintf(stderr, "%5d%c", code, (col+=6) >= 74 ? (col = 0, '\n') : ' ' );
- - }
- - putc( '\n', stderr );
- - exit( 0 );
- -}
- -
- -#ifdef XENIX_16
- -code_int stab1[8192] ;
- -code_int stab2[8192] ;
- -code_int stab3[8192] ;
- -code_int stab4[8192] ;
- -code_int stab5[8192] ;
- -code_int stab6[8192] ;
- -code_int stab7[8192] ;
- -code_int stab8[8192] ;
- -code_int * sorttab[8] = {stab1, stab2, stab3, stab4, stab5, stab6, stab7,
- - stab8 } ;
- -#define stabof(i) (sorttab[(i) >> 13][(i) & 0x1fff])
- -#else
- -code_int sorttab[SSIZE]; /* sorted pointers into htab */
- -#define stabof(i) (sorttab[i])
- -#endif
- -
- -dump_tab() /* dump string table */
- -{
- - register int i, first;
- - register ent;
- -#define STACK_SIZE 15000
- - int stack_top = STACK_SIZE;
- - register c;
- - unsigned mbshift ;
- -
- - if(do_decomp == 0) { /* compressing */
- - register int flag = 1;
- -
- - for(i=0; i<hsize; i++) { /* build sort pointers */
- - if((long)htabof(i) >= 0) {
- - stabof(codetabof(i)) = i;
- - }
- - }
- - first = block_compress ? FIRST : 256;
- - for(i = first; i < free_ent; i++) {
- - fprintf(stderr, "%5d: \"", i);
- - de_stack[--stack_top] = '\n';
- - de_stack[--stack_top] = '"';
- - stack_top = in_stack((htabof(stabof(i))>>maxbits)&0xff,
- - stack_top);
- -/* for(ent=htabof(stabof(i)) & ((1<<maxbits)-1); */
- - mbshift = ((1 << maxbits) - 1) ;
- - ent = htabof(stabof(i)) & mbshift ;
- - for(;
- - ent > 256;
- - /* ent=htabof(stabof(ent)) & ((1<<maxbits)-1)) { */
- - ent=htabof(stabof(ent)) & mbshift) {
- - stack_top = in_stack(htabof(stabof(ent)) >> maxbits,
- - stack_top);
- - }
- - stack_top = in_stack(ent, stack_top);
- - fwrite( &de_stack[stack_top], 1, STACK_SIZE-stack_top, stderr);
- - stack_top = STACK_SIZE;
- - }
- - } else if(!debug) { /* decompressing */
- -
- - for ( i = 0; i < free_ent; i++ ) {
- - ent = i;
- - c = tab_suffixof(ent);
- - if ( isascii(c) && isprint(c) )
- - fprintf( stderr, "%5d: %5d/'%c' \"",
- - ent, tab_prefixof(ent), c );
- - else
- - fprintf( stderr, "%5d: %5d/\\%03o \"",
- - ent, tab_prefixof(ent), c );
- - de_stack[--stack_top] = '\n';
- - de_stack[--stack_top] = '"';
- - for ( ; ent != NULL;
- - ent = (ent >= FIRST ? tab_prefixof(ent) : NULL) ) {
- - stack_top = in_stack(tab_suffixof(ent), stack_top);
- - }
- - fwrite( &de_stack[stack_top], 1, STACK_SIZE - stack_top, stderr );
- - stack_top = STACK_SIZE;
- - }
- - }
- -}
- -
- -int
- -in_stack(c, stack_top)
- - register c, stack_top;
- -{
- - if ( (isascii(c) && isprint(c) && c != '\\') || c == ' ' ) {
- - de_stack[--stack_top] = c;
- - } else {
- - switch( c ) {
- - case '\n': de_stack[--stack_top] = 'n'; break;
- - case '\t': de_stack[--stack_top] = 't'; break;
- - case '\b': de_stack[--stack_top] = 'b'; break;
- - case '\f': de_stack[--stack_top] = 'f'; break;
- - case '\r': de_stack[--stack_top] = 'r'; break;
- - case '\\': de_stack[--stack_top] = '\\'; break;
- - default:
- - de_stack[--stack_top] = '0' + c % 8;
- - de_stack[--stack_top] = '0' + (c / 8) % 8;
- - de_stack[--stack_top] = '0' + c / 64;
- - break;
- - }
- - de_stack[--stack_top] = '\\';
- - }
- - return stack_top;
- -}
- -#endif /* DEBUG */
- -
- -writeerr()
- -{
- - perror ( ofname );
- - unlink ( ofname );
- - exit ( 1 );
- -}
- -
- -copystat(ifname, ofname)
- -char *ifname, *ofname;
- -{
- - struct stat statbuf;
- - int mode;
- - time_t timep[2];
- -
- - fclose(stdout);
- - if (stat(ifname, &statbuf)) { /* Get stat on input file */
- - perror(ifname);
- - return;
- - }
- - if ((statbuf.st_mode & S_IFMT/*0170000*/) != S_IFREG/*0100000*/) {
- - if(quiet)
- - fprintf(stderr, "%s: ", ifname);
- - fprintf(stderr, " -- not a regular file: unchanged");
- - exit_stat = 1;
- - } else if (statbuf.st_nlink > 1) {
- - if(quiet)
- - fprintf(stderr, "%s: ", ifname);
- - fprintf(stderr, " -- has %d other links: unchanged",
- - statbuf.st_nlink - 1);
- - exit_stat = 1;
- - } else if (exit_stat == 2 && (!force)) { /* No compression: remove file.Z */
- - if(!quiet)
- - fprintf(stderr, " -- file unchanged");
- - } else { /* ***** Successful Compression ***** */
- - exit_stat = 0;
- - mode = statbuf.st_mode & 07777;
- - if (chmod(ofname, mode)) /* Copy modes */
- - perror(ofname);
- - chown(ofname, statbuf.st_uid, statbuf.st_gid); /* Copy ownership */
- - timep[0] = statbuf.st_atime;
- - timep[1] = statbuf.st_mtime;
- - utime(ofname, timep); /* Update last accessed and modified times */
- - if (unlink(ifname)) /* Remove input file */
- - perror(ifname);
- - if(!quiet)
- - fprintf(stderr, " -- replaced with %s", ofname);
- - return; /* Successful return */
- - }
- -
- - /* Unsuccessful return -- one of the tests failed */
- - if (unlink(ofname))
- - perror(ofname);
- -}
- -/*
- - * This routine returns 1 if we are running in the foreground and stderr
- - * is a tty.
- - */
- -foreground()
- -{
- - if(bgnd_flag) { /* background? */
- - return(0);
- - } else { /* foreground */
- - if(isatty(2)) { /* and stderr is a tty */
- - return(1);
- - } else {
- - return(0);
- - }
- - }
- -}
- -
- -onintr ( )
- -{
- - unlink ( ofname );
- - exit ( 1 );
- -}
- -
- -oops ( ) /* wild pointer -- assume bad input */
- -{
- - if ( do_decomp == 1 )
- - fprintf ( stderr, "uncompress: corrupt input\n" );
- - unlink ( ofname );
- - exit ( 1 );
- -}
- -
- -cl_block () /* table clear for block compress */
- -{
- - register long int rat;
- -
- - checkpoint = in_count + CHECK_GAP;
- -#ifdef DEBUG
- - if ( debug ) {
- - fprintf ( stderr, "count: %ld, ratio: ", in_count );
- - prratio ( stderr, in_count, bytes_out );
- - fprintf ( stderr, "\n");
- - }
- -#endif /* DEBUG */
- -
- - if(in_count > 0x007fffff) { /* shift will overflow */
- - rat = bytes_out >> 8;
- - if(rat == 0) { /* Don't divide by zero */
- - rat = 0x7fffffff;
- - } else {
- - rat = in_count / rat;
- - }
- - } else {
- - rat = (in_count << 8) / bytes_out; /* 8 fractional bits */
- - }
- - if ( rat > ratio ) {
- - ratio = rat;
- - } else {
- - ratio = 0;
- -#ifdef DEBUG
- - if(verbose)
- - dump_tab(); /* dump string table */
- -#endif
- - cl_hash ( (count_int) hsize );
- - free_ent = FIRST;
- - clear_flg = 1;
- - output ( (code_int) CLEAR );
- -#ifdef DEBUG
- - if(debug)
- - fprintf ( stderr, "clear\n" );
- -#endif /* DEBUG */
- - }
- -}
- -
- -cl_hash(hsize) /* reset code table */
- - register count_int hsize;
- -{
- -#ifndef XENIX_16 /* Normal machine */
- - register count_int *htab_p = htab+hsize;
- -#else
- - register j;
- - register long k = hsize;
- - register count_int *htab_p;
- -#endif
- - register long i;
- - register long m1 = -1;
- -
- -#ifdef XENIX_16
- - for(j=0; j<=8 && k>=0; j++,k-=8192) {
- - i = 8192;
- - if(k < 8192) {
- - i = k;
- - }
- - htab_p = &(htab[j][i]);
- - i -= 16;
- - if(i > 0) {
- -#else
- - i = hsize - 16;
- -#endif
- - do { /* might use Sys V memset(3) here */
- - *(htab_p-16) = m1;
- - *(htab_p-15) = m1;
- - *(htab_p-14) = m1;
- - *(htab_p-13) = m1;
- - *(htab_p-12) = m1;
- - *(htab_p-11) = m1;
- - *(htab_p-10) = m1;
- - *(htab_p-9) = m1;
- - *(htab_p-8) = m1;
- - *(htab_p-7) = m1;
- - *(htab_p-6) = m1;
- - *(htab_p-5) = m1;
- - *(htab_p-4) = m1;
- - *(htab_p-3) = m1;
- - *(htab_p-2) = m1;
- - *(htab_p-1) = m1;
- - htab_p -= 16;
- - } while ((i -= 16) >= 0);
- -#ifdef XENIX_16
- - }
- - }
- -#endif
- - for ( i += 16; i > 0; i-- )
- - *--htab_p = m1;
- -}
- -
- -prratio(stream, num, den)
- -FILE *stream;
- -long int num, den;
- -{
- - register int q; /* Doesn't need to be long */
- -
- - if(num > 214748L) { /* 2147483647/10000 */
- - q = num / (den / 10000L);
- - } else {
- - q = 10000L * num / den; /* Long calculations, though */
- - }
- - if (q < 0) {
- - putc('-', stream);
- - q = -q;
- - }
- - fprintf(stream, "%d.%02d%%", q / 100, q % 100);
- -}
- -
- -version()
- -{
- - fprintf(stderr, "%s\n", rcs_ident);
- - fprintf(stderr, "Options: ");
- -#ifdef vax
- - fprintf(stderr, "vax, ");
- -#endif
- -#ifdef NO_UCHAR
- - fprintf(stderr, "NO_UCHAR, ");
- -#endif
- -#ifdef SIGNED_COMPARE_SLOW
- - fprintf(stderr, "SIGNED_COMPARE_SLOW, ");
- -#endif
- -#ifdef XENIX_16
- - fprintf(stderr, "XENIX_16, ");
- -#endif
- -#ifdef COMPATIBLE
- - fprintf(stderr, "COMPATIBLE, ");
- -#endif
- -#ifdef DEBUG
- - fprintf(stderr, "DEBUG, ");
- -#endif
- -#ifdef BSD4_2
- - fprintf(stderr, "BSD4_2, ");
- -#endif
- - fprintf(stderr, "BITS = %d\n", BITS);
- -}
- *-*-END-of-src/compress.c-*-*
- echo x - src/virtterm.c 1>&2
- sed 's/.//' >src/virtterm.c <<'*-*-END-of-src/virtterm.c-*-*'
- -/*
- - * Virtual terminal handler
- - * Written by Kenneth Almquist, AGS Computers (HO 4C601, X7105).
- - * Modified by Stephen Hemminger, to use TERMCAP (without curses)
- - */
- -
- -#ifdef SCCSID
- -static char *SccsId = "@(#)virtterm.c 1.12 10/29/86";
- -#endif /* SCCSID */
- -
- -/*LINTLIBRARY*/
- -
- -#include <stdio.h>
- -#include <ctype.h>
- -#include <sys/types.h>
- -#include <sys/ioctl.h>
- -#include <signal.h>
- -#ifdef USG
- -#include <termio.h>
- -#else /* !USG */
- -#include <sgtty.h>
- -#endif /* !USG */
- -
- -/*
- - * These values for MAXPLEN and MAXLLEN are used to dimension arrays
- - * that hold strings of relative cursor motions. The actual arrays that
- - * are used to hold screen images are malloc'd.
- - */
- -#define MAXPLEN 90
- -#define MAXLLEN 160
- -
- -#define BOTLINE (ROWS - 1)
- -#define DIRTY 01
- -
- -/* terminal escape sequences from termcap */
- -#define HO _tstr[0] /* home */
- -#define CL _tstr[1] /* clear screen */
- -#define CD _tstr[2] /* clear to end of screen */
- -#define CE _tstr[3] /* clear to end of line */
- -#define xUP _tstr[4] /* up one line */
- -#define DO _tstr[5] /* down one line */
- -#define US _tstr[6] /* underline */
- -#define UE _tstr[7] /* underline end */
- -#define BT _tstr[8] /* backtab */
- -#define xBC _tstr[9] /* backspace */
- -#define AL _tstr[10] /* insert line */
- -#define DL _tstr[11] /* delete line */
- -#define CM _tstr[12] /* cursor move */
- -#define CH _tstr[13] /* cursor horizontal move */
- -#define CV _tstr[14] /* cursor vertical move */
- -#define CS _tstr[15] /* scrolling region */
- -#define SF _tstr[16] /* scroll forwards */
- -#define SR _tstr[17] /* scroll backwards */
- -#define TI _tstr[18] /* start cursor mode */
- -#define TE _tstr[19] /* end cursor mode */
- -#define TA _tstr[20] /* tab char (if not \t) */
- -#define CR _tstr[21] /* carriage return (if not \r) */
- -#define xPC _tstr[22] /* for reading pad character */
- -char PC; /* pad character */
- -char *BC, *UP; /* external variables for tgoto */
- -
- -static char sname[] = "hoclcdceupdousuebtbcaldlcmchcvcssfsrtitetacrpc";
- -char *_tstr[23];
- -int HOlen; /* length of HO string */
- -
- -
- -/* terminal flags */
- -#define BS _tflg[0] /* can backspace */
- -#define AM _tflg[1] /* has auto margins */
- -#define XN _tflg[2] /* no newline after wrap */
- -#define RET !_tflg[3] /* has carriage return */
- -#define NS _tflg[4] /* has SF (scroll forward) */
- -#define PT _tflg[5] /* has tabs */
- -#define XT _tflg[6] /* tabs are destructive */
- -int GT = 1; /* tab stops on terminal are set */
- -
- -static char bname[] = "bsamxnncnsptxt";
- -char _tflg[7];
- -
- -
- -extern char *tgoto(), *tgetstr();
- -extern char *getenv(), *strcpy();
- -
- -#define ULINE 0200
- -
- -/* Constants accessable by user */
- -int hasscroll; /* scrolling type, 0 == no scrolling */
- -int ROWS; /* number of lines on screen */
- -int COLS; /* width of screen */
- -
- -struct line {
- - char len;
- - char flags;
- - char *l; /* pointer to actual line text, NO NULL @ end */
- -};
- -
- -int _row, _col;
- -int _srow, _scol;
- -struct line *_virt; /* what we want the screen to look like */
- -struct line *_actual; /* What it actually looks like */
- -int _uline = 0;
- -int _junked = 1;
- -int _curjunked;
- -int _dir = 1;
- -int _shifttop, _shiftbot;
- -int _shift;
- -int _scratched;
- -int vputc();
- -
- -/*
- - * Tell refresh to shift lines in region upwards count lines. Count
- - * may be negative. The virtual image is not shifted; this may change
- - * later. The variable _scratched is set to supress all attempts to
- - * shift.
- - */
- -
- -ushift(top, bot, count)
- -{
- - if (_scratched)
- - return;
- - if (_shift != 0 && (_shifttop != top || _shiftbot != bot)) {
- - _scratched++;
- - return;
- - }
- - _shifttop = top;
- - _shiftbot = bot;
- - _shift += count;
- -}
- -
- -/*
- - * generate a beep on the terminal
- - */
- -beep()
- -{
- - vputc('\7');
- -}
- -
- -/*
- - * Move to one line below the bottom of the screen.
- - */
- -botscreen()
- -{
- - _amove(BOTLINE, 0);
- - vputc('\n');
- - vflush();
- -}
- -
- -move(row, col)
- -{
- - if (row < 0 || row >= ROWS || col < 0 || col >= COLS)
- - return;
- - _row = row;
- - _col = col;
- -}
- -
- -
- -
- -/*
- - * Output string at specified location.
- - */
- -mvaddstr(row, col, str)
- -char *str;
- -{
- - move(row, col);
- - addstr(str);
- -}
- -
- -addstr(s)
- -char *s;
- -{
- - register char *p;
- - register struct line *lp;
- - register int col = _col;
- -
- - lp = &_virt[_row];
- - if (lp->len < col) {
- - p = &lp->l[lp->len];
- - while (lp->len < col) {
- - *p++ = ' ';
- - lp->len++;
- - }
- - }
- - for (p = s; *p != '\0'; p++) {
- - if (*p == '\n') {
- - lp->len = col;
- - lp->flags |= DIRTY;
- - col = 0;
- - if (++_row >= ROWS)
- - _row = 0;
- - lp = &_virt[_row];
- - }
- - else {
- - lp->l[col] = *p;
- - lp->flags |= DIRTY;
- - if (++col >= COLS) {
- - lp->len = COLS;
- - col = 0;
- - if (++_row >= ROWS)
- - _row = 0;
- - lp = &_virt[_row];
- - }
- - }
- - }
- - if (lp->len <= col)
- - lp->len = col;
- - _col = col;
- -}
- -
- -addch(c)
- -{
- - register struct line *lp;
- - register char *p;
- -
- - lp = &_virt[_row];
- - if (lp->len < _col) {
- - p = &lp->l[lp->len];
- - while (lp->len < _col) {
- - *p++ = ' ';
- - lp->len++;
- - }
- - }
- - lp->l[_col] = c;
- - if (lp->len == _col)
- - lp->len++;
- - if (++_col >= COLS) {
- - _col = 0;
- - if (++_row >= ROWS)
- - _row = 0;
- - }
- - lp->flags |= DIRTY;
- -}
- -
- -/*
- - * Clear an entire line.
- - */
- -clrline(row)
- -{
- - register struct line *lp;
- -
- - lp = &_virt[row];
- - if (lp->len > 0) {
- - lp->len = 0;
- - lp->flags |= DIRTY;
- - }
- -}
- -
- -erase()
- -{
- - register i;
- -
- - for (i = 0; i < ROWS; i++) {
- - _virt[i].len = 0;
- - _virt[i].flags |= DIRTY;
- - }
- -}
- -
- -refresh()
- -{
- - register i;
- - register char *p, *q;
- - register int j, len;
- -
- - if (checkin())
- - return;
- - i = 1;
- - if (_junked) {
- - _sclear();
- - _junked = 0;
- - } else if (! _scratched) {
- - if (_shift > 0) {
- - _ushift(_shifttop, _shiftbot, _shift);
- - } else if (_shift < 0) {
- - i = _dshift(_shifttop, _shiftbot, -_shift);
- - } else {
- - i = _dir;
- - }
- - }
- - _dir = i;
- - _shift = 0;
- - if (checkin())
- - return;
- - _fixlines();
- - for (i = _dir > 0 ? 0 : BOTLINE; i >= 0 && i < ROWS; i += _dir) {
- - if ((_virt[i].flags & DIRTY) == 0)
- - continue;
- - _ckclrlin(i); /* decide whether to do a clear line */
- - /* probably should consider cd too */
- - len = _virt[i].len;
- - if (_actual[i].len < len)
- - len = _actual[i].len;
- - p = _virt[i].l;
- - q = _actual[i].l;
- - for (j = 0; j < len; j++) {
- - if (*p != *q) {
- - /* Inline test for speed */
- - if (i != _srow || j != _scol || _curjunked)
- - _amove(i, j);
- - _aputc(*p);
- - *q = *p;
- - }
- - p++;
- - q++;
- - }
- - len = _virt[i].len;
- - if (_actual[i].len > len) {
- - _clrtoeol(i, len);
- - } else {
- - for (; j < len; j++) {
- - if (*p != ' ') {
- - /* Inline test for speed */
- - if (i != _srow || j != _scol || _curjunked)
- - _amove(i, j);
- - _aputc(*p);
- - }
- - *q++ = *p++;
- - }
- - _actual[i].len = len;
- - }
- - if (checkin())
- - return;
- - }
- - _dir = 1;
- - _amove(_row, _col);
- - vflush(); /* flush output buffer */
- - _scratched = 0;
- -}
- -
- -_dshift(top, bot, count)
- -{
- - register i;
- -
- - if (count >= bot - top || hasscroll < 4) { /* must have CS or AL/DL */
- - _scratched++;
- - return 1;
- - }
- - for (i = bot - count; _actual[i].len == 0; i--)
- - if (i == top)
- - return 1;
- - for (i = top; i <= bot; i++)
- - _virt[i].flags |= DIRTY;
- - for (i = bot; i >= top + count; i--) {
- - /* FIXME, this should be done by recirculating the pointers */
- - register j;
- - j = _actual[i].len = _actual[i - count].len;
- - _actual[i].flags = _actual[i - count].flags;
- - strncpy(_actual[i].l, _actual[i - count].l, j);
- - }
- - for (; i >= top; i--)
- - _actual[i].len = 0;
- -
- - if (hasscroll != 5) { /* can we define scrolling region, and scroll back */
- - tputs(tgoto(CS, bot, top), 1, vputc);/* define scroll region */
- - _curjunked = 1;
- - _amove(top, 0);
- - for (i = count; --i >= 0;)
- - tputs(SR, 1, vputc);/* scroll back */
- - tputs(tgoto(CS, BOTLINE, 0), 1, vputc);
- - _curjunked = 1;
- - } else {
- - _amove(bot - count + 1, 0);
- - if (CD && bot == BOTLINE)
- - tputs(CD, 1, vputc);
- - else {
- - for (i = count; --i >= 0;)
- - tputs(DL, ROWS - _srow, vputc);
- - }
- - _amove(top, 0);
- - for (i = count; --i >= 0;)
- - tputs(AL, ROWS - _srow, vputc);
- - }
- - return -1;
- -}
- -
- -
- -_ushift(top, bot, count)
- -{
- - register i;
- -
- - if (count >= bot - top || hasscroll == 0) {
- - _scratched++;
- - return;
- - }
- - for (i = top + count; _actual[i].len == 0; i++)
- - if (i == bot)
- - return;
- - if (hasscroll == 1 || hasscroll == 3) {
- - /* we cheat and shift the entire screen */
- - /* be sure we are shifting more lines into than out of position */
- - if ((bot - top + 1) - count <= ROWS - (bot - top + 1))
- - return;
- - top = 0, bot = BOTLINE;
- - }
- - for (i = top; i <= bot; i++)
- - _virt[i].flags |= DIRTY;
- - for (i = top; i <= bot - count; i++) {
- - /* FIXME, this should be done by recirculating the pointers */
- - register int j;
- - j = _actual[i].len = _actual[i + count].len;
- - _actual[i].flags = _actual[i + count].flags;
- - strncpy(_actual[i].l, _actual[i + count].l, j);
- - }
- - for (; i <= bot; i++)
- - for (; i <= bot; i++)
- - _actual[i].len = 0;
- -
- - if (hasscroll != 5) {
- - if (top != 0 || bot != BOTLINE) {
- - tputs(tgoto(CS, bot, top), 0, vputc);
- - _curjunked = 1;
- - }
- - _amove(bot, 0); /* move to bottom */
- - for (i = 0; i < count; i++) {
- - if (SF) /* scroll forward */
- - tputs(SF, 1, vputc);
- - else
- - vputc('\n');
- - }
- - if (top != 0 || bot != BOTLINE) {
- - tputs(tgoto(CS, BOTLINE, 0), 0, vputc);
- - _curjunked = 1;
- - }
- - } else {
- - _amove(top, 0);
- - for (i = count; --i >= 0;)
- - tputs(DL, ROWS - _srow, vputc);
- - if (bot < BOTLINE) {
- - _amove(bot - count + 1, 0);
- - for (i = count; --i >= 0;)
- - tputs(AL, ROWS - _srow, vputc);
- - }
- - }
- -}
- -
- -_sclear()
- -{
- - register struct line *lp;
- -
- - tputs(CL, 0, vputc);
- - _srow = _scol = 0;
- - for (lp = _actual; lp < &_actual[ROWS]; lp++) {
- - lp->len = 0;
- - }
- - for (lp = _virt; lp < &_virt[ROWS]; lp++) {
- - if (lp->len != 0)
- - lp->flags |= DIRTY;
- - }
- -}
- -
- -_clrtoeol(row, col)
- -{
- - register struct line *lp = &_actual[row];
- - register i;
- -
- - if (CE && lp->len > col + 1) {
- - _amove(row, col);
- - tputs(CE, 1, vputc);
- - } else {
- - for (i = col ; i < lp->len ; i++) {
- - if (lp->l[i] != ' ') {
- - _amove(row, i);
- - _aputc(' ');
- - }
- - }
- - }
- - lp->len = col;
- -}
- -
- -_fixlines()
- -{
- - register struct line *lp;
- - register char *p;
- - register int i;
- -
- - for (i = 0; i < ROWS; i++) {
- - lp = &_virt[i];
- - if (lp->flags & DIRTY) {
- - for (p = &lp->l[lp->len]; --p >= lp->l && *p == ' ';)
- - ;
- - lp->len = (int) (p - lp->l) + 1;
- - if (lp->len == _actual[i].len && strncmp(lp->l, _actual[i].l, lp->len) == 0)
- - lp->flags &= ~DIRTY;
- - }
- - }
- -}
- -
- -
- -/*
- - * Consider clearing the line before overwriting it.
- - * We always clear a line if it has underlined characters in it
- - * because these can cause problems. Otherwise decide whether
- - * that will decrease the number of characters to change. This
- - * routine could probably be simplified with no great loss.
- - */
- -
- -_ckclrlin(i)
- -{
- - int eval;
- - int len;
- - int first;
- - register struct line *vp, *ap;
- - register int j;
- -
- - if (!CE)
- - return;
- - ap = &_actual[i];
- - vp = &_virt[i];
- - len = ap->len;
- - eval = -strlen(CE);
- - if (len > vp->len) {
- - len = vp->len;
- - eval = 0;
- - }
- - for (j = 0; j < len && vp->l[j] == ap->l[j]; j++)
- - ;
- - if (j == len)
- - return;
- - first = j;
- - while (j < len) {
- - if (vp->l[j] == ' ') {
- - if (ap->l[j] != ' ') {
- - while (++j < len && vp->l[j] == ' ' && ap->l[j] != ' ') {
- - eval++;
- - }
- - if (j == len)
- - eval++;
- - continue;
- - }
- - }
- - else {
- - if (vp->l[j] == ap->l[j]) {
- - while (++j < len && vp->l[j] == ap->l[j]) {
- - eval--;
- - }
- - continue;
- - }
- - }
- - j++;
- - }
- - if (US) {
- - for (j = 0 ; j < ap->len ; j++) {
- - if (ap->l[j] & ULINE) {
- - eval = 999;
- - if (first > j)
- - first = j;
- - break;
- - }
- - }
- - }
- - for (j = first; --j >= 0;)
- - if (vp->l[j] != ' ')
- - break;
- - if (j < 0)
- - first = 0;
- - if (eval > 0) {
- - _amove(i, first);
- - tputs(CE, 0, vputc);
- - _actual[i].len = first;
- - }
- -}
- -
- -
- -
- -/*
- - * Move routine
- - * first compute direct cursor address string and cost
- - * then relative motion string and cost,
- - * then home then relative and cost
- - * choose smallest and do it.
- - *
- - * The plod stuff is to build the strings (with padding) then decide
- - */
- -static char *plodstr; /* current location in relmove string */
- -
- -plodput(c)
- -{
- - *plodstr++ = c;
- -}
- -
- -/* FIXME: speedup 1-char horiz moves: print the char that's there. */
- -/* FIXME: avoid funniness if cm works. */
- -/* FIXME: Avoid setul(0) if cursor motion OK in standout (XM?) */
- -_amove(row, col)
- -{
- - char direct[20];
- - char rel[MAXPLEN*10 + MAXLLEN*10]; /* longest move is full screen */
- - char ho[MAXPLEN*10 + MAXLLEN*10];
- - int cost, newcost;
- - register char *movstr;
- -
- - if (row == _srow && col == _scol && _curjunked == 0)
- - return;
- - if (_uline)
- - _setul(0); /* Inline test for speed */
- -
- - cost = 999;
- - if (CM) {
- - plodstr = direct;
- - tputs(tgoto(CM, col, row), 0, plodput);
- - cost = plodstr - direct;
- - movstr = direct;
- - }
- - if (_curjunked == 0) {
- - plodstr = rel;
- - if (_vmove(_srow, row) >= 0
- - && (plodstr - rel) < cost /* after vmove */
- - && _hmove(_scol, col, row) >= 0
- - && (newcost = plodstr - rel) < cost) { /* after both */
- - cost = newcost;
- - movstr = rel;
- - }
- - }
- - if (cost > HOlen) { /* is it worth calculating */
- - plodstr = ho;
- - tputs(HO, 0, plodput);
- - if (_vmove(0, row) >= 0
- - && (plodstr - ho) < cost /* after ho, vmove */
- - && _hmove(0, col, row) >= 0
- - && (newcost = plodstr - ho) < cost) { /* after all three */
- - cost = newcost;
- - movstr = ho;
- - }
- - }
- -
- - if (cost < 999)
- - while (--cost >= 0)
- - vputc(*movstr++);
- -
- - _srow = row;
- - _scol = col;
- - _curjunked = 0;
- -}
- -
- -_vmove(orow, nrow)
- -{
- - char direct[128];
- - char *saveplod = plodstr;
- -
- - if (CV) {
- - plodstr = direct;
- - tputs(tgoto(CV, nrow, nrow), 0, plodput);
- - *plodstr = '\0';
- - plodstr = saveplod;
- - }
- - if (orow > nrow) { /* cursor up */
- - if (! UP)
- - return -1;
- - while (orow > nrow) {
- - tputs(UP, 1, plodput);
- - orow--;
- - }
- - }
- - while (orow < nrow) { /* cursor down */
- - if (DO)
- - tputs(DO, 1, plodput);
- - else
- - *plodstr++ = '\n';
- - orow++;
- - }
- - if (CV && plodstr - saveplod >= strlen(direct)) {
- - register char *p;
- - plodstr = saveplod;
- - for (p = direct ; *plodstr = *p++ ; plodstr++)
- - ;
- - }
- - return 0;
- -}
- -
- -_hmove(ocol, ncol, row)
- -{
- - char direct[128];
- - char ret[MAXLLEN*10];
- - char *saveplod = plodstr;
- - char *movstr;
- - int cost, newcost;
- -
- - cost = 999;
- - if (CH) {
- - plodstr = direct;
- - tputs(tgoto(CH, ncol, ncol), 0, plodput);
- - cost = plodstr - direct;
- - movstr = direct;
- - plodstr = saveplod;
- - }
- - if (RET && ocol > ncol) { /* consider doing carriage return */
- - plodstr = ret;
- - if (CR)
- - tputs(CR, 1, plodput);
- - else
- - *plodstr++ = '\r';
- - if (_relhmove(0, ncol, row) >= 0
- - && (newcost = plodstr - ret) < cost) {
- - cost = newcost;
- - movstr = ret;
- - }
- - plodstr = saveplod;
- - }
- - if (_relhmove(ocol, ncol, row) < 0) {
- - if (cost == 999)
- - return -1;
- - goto copy;
- - }
- - if (plodstr - saveplod > cost) {
- -copy: plodstr = saveplod;
- - while (--cost >= 0)
- - *plodstr++ = *movstr++;
- - }
- - return 0;
- -}
- -
- -_relhmove(ocol, ncol, row)
- -{
- - int tab;
- -
- - if (ocol < ncol && PT && GT) { /* tab (nondestructive) */
- - while ((tab = (ocol + 8) & ~07) <= ncol) {
- - if (TA)
- - tputs(TA, 1, plodput);
- - else
- - *plodstr++ = '\t';
- - ocol = tab;
- - }
- - if (tab < COLS && tab - ncol < ncol - ocol) {
- - if (TA)
- - tputs(TA, 1, plodput);
- - else
- - *plodstr++ = '\t';
- - ocol = tab;
- - }
- - } else if (BT && GT && ocol > ncol) { /* backwards tab */
- - while ((tab = (ocol - 1) &~ 07) >= ncol) {
- - if (BS && tab == ocol - 1) {
- - if (BC)
- - tputs(BC, 1, plodput);
- - else
- - *plodstr++ = '\b';
- - } else
- - tputs(BT, 1, plodput);
- - ocol = tab;
- - }
- - if (ncol - tab + 1 < ocol - ncol) {
- - tputs(BT, 1, plodput);
- - ocol = tab;
- - }
- - }
- - if (ocol > ncol) { /* cursor left */
- - if (! BS)
- - return -1;
- - while (ocol > ncol) {
- - if (BC != NULL)
- - tputs(BC, 1, plodput);
- - else
- - *plodstr++ = '\b';
- - ocol--;
- - }
- - }
- - if (ocol < ncol) { /* cursor right */
- - register struct line *lp = &_actual[row];
- - /*
- - * This code doesn't move over underlined characters properly,
- - * but in practice this doesn't seem to matter.
- - */
- - while (ocol < ncol) {
- - if (ocol < lp->len)
- - *plodstr++ = lp->l[ocol];
- - else
- - *plodstr++ = ' ';
- - ocol++;
- - }
- - }
- - return 0;
- -}
- -
- -_aputc(c)
- -{
- - if (_uline != (c & ULINE)) /* Inline for speed */
- - _setul(c & ULINE);
- - if (++_scol >= COLS) {
- - if (_srow == ROWS - 1) {
- - /* Don't ever paint last char of last line */
- - _scol--;
- - return;
- - }
- - _curjunked++; /* Don't assume AM is right */
- - }
- - vputc(c & ~ULINE);
- -}
- -
- -
- -_setul(on)
- -{
- - if (on) {
- - if (_uline == 0 && US != NULL) {
- - tputs(US, 1, vputc);
- - _uline = ULINE;
- - }
- - }
- - else {
- - if (_uline != 0 && UE != NULL) {
- - tputs(UE, 1, vputc);
- - _uline = 0;
- - }
- - }
- -}
- -
- -/*
- - * Initialize termcap strings for later use.
- - */
- -
- -/*
- - * Hacks to help with some Tek terminals
- - * rad@tek
- - */
- -int tputs_len;
- -countit(c) { tputs_len++; }
- -
- -initterm()
- -{
- - static char tcbuf[1024]; /* termcap buffer */
- - register char *cp;
- -#ifdef USG
- - struct termio tio;
- -#else /* !USG */
- - struct sgttyb ttyb;
- -#endif /* !USG */
- -
- - if ((cp = getenv("TERM")) == NULL)
- - xerror("TERM not set in environment");
- -
- - switch (tgetent(tcbuf, cp)) {
- - case 0:
- - xerror("Terminal not found in TERMCAP");
- - case -1:
- - xerror("Can't open /etc/termcap");
- - case 1:
- - break;
- - }
- -#ifdef TIOCGWINSZ
- - {
- - struct winsize ws;
- - int winch();
- -
- - COLS = ROWS = -1;
- - if(ioctl(1, TIOCGWINSZ, &ws) == 0) {
- - ROWS = ws.ws_row;
- - COLS = ws.ws_col;
- - }
- - if(ROWS <= 0)
- - ROWS = tgetnum("li");
- - if(COLS <= 0)
- - COLS = tgetnum("co");
- - if ((ROWS <= 0) || (COLS <= 0))
- - xerror("Can't get screen size");
- -
- - signal(SIGWINCH, winch); /* allow for changing window size */
- - }
- -#else /* !TIOCGWINSZ */
- - if ((ROWS = tgetnum("li")) == -1
- - || (COLS = tgetnum("co")) == -1)
- - xerror("Can't get screen size");
- -#endif /* !TIOCGWINSZ */
- - _zap();
- -
- - if (CL == NULL)
- - xerror ("No clear screen defined");
- -
- - if (HO == NULL && CM == NULL)
- - xerror("No home or cursor addressing");
- - if (HO)
- - HOlen = strlen(HO);
- - else
- - HOlen = 999;
- -
- - PC = xPC ? xPC[0] : 0;
- - BC = xBC;
- - UP = xUP;
- - /*
- - * _vmove() may be called with a full-screen traverse,
- - * meaning it will put the UP (along with any padding) into
- - * the buffer as many as MAXPLEN times. This means that
- - * if the UP string would be more than 10 chars long (defined
- - * in _amove() ), the buffer might be overflowed (assuming
- - * CH is also large).
- - * This actually occurs with the Tek4023 termcap, where :up=1000UP:
- - * is used to fake vi into using :cm instead, due to the fact
- - * that a 4023 can't do upline relative motion at all.
- - * -rdoty@tek
- - */
- - if (UP) {
- - tputs_len = 0;
- - tputs(UP, 1, countit);
- - if (tputs_len > 10 )
- - UP = 0;
- - }
- -
- - if (tgetnum("ug") > 0)
- - US = UE = NULL;
- -
- - if (XT) /* Destructive tab code not included */
- - PT = 0; /* to keep things simple */
- -
- -#ifdef USG
- - if (ioctl(0, TCGETA, &tio) == 0)
- - GT = tio.c_oflag&TAB3;
- -#else /* !USG */
- - if (ioctl(0, TIOCGETP, &ttyb) == 0)
- - GT = ttyb.sg_flags&XTABS;
- -#endif /* !USG */
- -
- - {
- - char *thelines;
- - int i;
- - char *malloc();
- -
- - thelines = malloc(2 * ROWS * COLS);
- - _virt = (struct line *)malloc(2 * ROWS * sizeof (struct line));
- - _actual = _virt + ROWS;
- - for (i = 0; i < ROWS; i++) {
- - _virt[i].len = 0;
- - _virt[i].flags = 0;
- - _actual[i].len = 0;
- - _actual[i].flags = 0;
- - _virt[i].l = thelines;
- - thelines += COLS;
- - _actual[i].l = thelines;
- - thelines += COLS;
- - }
- - }
- -
- - /* Select article scrolling algorithm. We prefer scrolling region
- - over insert/delete line because it's faster on the HP */
- - hasscroll = 0;
- - if (!NS) {
- - hasscroll = 1;
- - if (SR)
- - hasscroll = 3;
- - if (CS)
- - hasscroll++;
- - }
- - if (AL && DL && hasscroll != 4)
- - hasscroll = 5;
- -}
- -
- -rawterm()
- -{
- - if (TI != NULL)
- - tputs(TI, 0, vputc);
- -}
- -
- -cookedterm()
- -{
- - if (TE != NULL) {
- - tputs(TE, 0, vputc);
- - vflush();
- - }
- -}
- -
- -/* get strings from termcap */
- -_zap()
- -{
- - static char tstrbuf[1024];
- - static char *tp;
- - register char *namp, **sp, *bp;
- -
- - tp = tstrbuf;
- - sp = _tstr;
- - for (namp = sname; *namp; namp += 2) {
- - *sp++ = tgetstr(namp, &tp);
- - }
- - bp = _tflg;
- - for (namp = bname; *namp; namp += 2) {
- - *bp++ = tgetflag(namp, &tp);
- - }
- -}
- -#ifdef TIOCGWINSZ
- -/*
- - * window changed size -- update ROWS and COLS
- - * and then redraw screen
- - */
- -winch()
- -{
- - struct winsize ws;
- - int cols, rows;
- -
- - cols = rows = -1;
- - if(ioctl(1, TIOCGWINSZ, &ws) == 0) {
- - rows = ws.ws_row;
- - cols = ws.ws_col;
- - }
- - if (rows == ROWS && cols == COLS) { /* just redraw it if no change */
- - _junked = 1; /* redraw */
- - updscr();
- - return;
- - }
- -
- - if(rows > 0)
- - ROWS = rows;
- - if(cols > 0)
- - COLS = cols;
- -
- - if (ROWS > MAXPLEN)
- - ROWS = MAXPLEN;
- - if (COLS > MAXLLEN) {
- - COLS = MAXLLEN;
- - AM = XN = 1;
- - }
- -
- - winch_upd();
- -}
- -#endif TIOCGWINSZ
- *-*-END-of-src/virtterm.c-*-*
- echo x - src/decode.c 1>&2
- sed 's/.//' >src/decode.c <<'*-*-END-of-src/decode.c-*-*'
- -#include <stdio.h>
- -
- -#ifdef SCCSID
- -static char *SccsId = "@(#)decode.c 1.3 5/15/85";
- -#endif /* SCCSID */
- -
- -/*
- - * This program is the inverse of encode
- - *
- - * It collects runs of 12 characters, combines pairs of those
- - * to form 6 13 bit numbers, extracts the top bit of each of
- - * those to make a 13th 6 bit character, and splits each of
- - * the remaining 6 12 bit numbers to form 12 6 bit ones.
- - *
- - * The strings of 6 bit numbers are collected into groups of
- - * 4 and converted into 3 8 bit characters.
- - *
- - * Now all that would be trivial, if we didn't need to worry
- - * about ending all this correctly. About 1/2 of the following
- - * program wouldn't be here if the ending didn't matter....
- - */
- -
- -/*
- - * the following pair of characters can never occur as a pair
- - * in legal input (since (90 * 91 + 90) > 2^13) - they are
- - * noticed at the beginning of a 12 char block, and serve to
- - * indicate that this block is the terminator. The character
- - * immediately following is the (expanded) terminator length.
- - */
- -#define ENDMARK1 ((90*91 + 90) / 91)
- -#define ENDMARK2 ((90*91 + 90) % 91)
- -
- -main()
- -{
- - register c;
- - register char *p;
- - register i;
- - register first = 1;
- - register cnt = 0;
- - int errcnt = 0;
- - char b12[12];
- - char c12[12];
- -
- - p = b12;
- - i = 12;
- -
- - while ((c = getchar()) != EOF) {
- - if (c < ' ' || c >= (' ' + 91)) {
- - if (errcnt++ == 0)
- - fprintf(stderr, "decode: Bad data\n");
- - continue;
- - }
- - if (i == 10 && p[-1] == ENDMARK1 && p[-2] == ENDMARK2) {
- - cnt = c - ' ';
- - i = 12;
- - p -= 2;
- - continue;
- - }
- - *p++ = c - ' ';
- - if (--i == 0) {
- - if (p == &b12[12]) {
- - if (!first)
- - pack12(c12, 12, 0);
- - else
- - first = 0;
- - p = c12;
- - } else {
- - pack12(b12, 12, 0);
- - p = b12;
- - }
- - i = 12;
- - }
- - }
- -
- - if (p >= &b12[0] && p < &b12[12]) {
- - if (!first)
- - pack12(c12, 12, i == 12 ? cnt : 0);
- - } else
- - pack12(b12, 12, i == 12 ? cnt : 0);
- -
- - if (i != 12) {
- - if (p >= &b12[0] && p < &b12[12])
- - pack12(b12, 12-i, cnt);
- - else
- - pack12(c12, 12-i, cnt);
- - }
- -
- - exit(0);
- -}
- -
- -static char b4[4];
- -static int cnt = 0;
- -
- -pack12(p, n, last)
- - register char *p;
- - register n;
- - int last;
- -{
- - register i;
- - register char *q;
- - char b13[13];
- -
- - {
- - register c;
- - register c13;
- -
- - q = b13;
- - c13 = 0;
- -
- - for (i = 0; i < n; i += 2) {
- - c = *p++ * 91;
- - c += *p++;
- - c13 <<= 1;
- - if (c & (1 << 12))
- - c13 |= 1;
- - *q++ = (c >> 6) & 0x3f;
- - *q++ = c & 0x3f;
- - }
- - *q++ = c13;
- - if (last)
- - q = &b13[last];
- - }
- -
- - p = b13;
- - n = q - p;
- - i = cnt;
- - q = &b4[cnt];
- -
- - while (--n > 0) {
- - *q++ = *p++;
- - if (++i == 4) {
- - char b3[3];
- - register char *b = b4;
- -
- - /* inline expansion of pack6bit, to save calls ... */
- -
- - q = b3;
- - *q++ = (b[0] << 2) | ((b[1] >> 4) & 0x3);
- - *q++ = (b[1] << 4) | ((b[2] >> 2) & 0xf);
- - *q = (b[2] << 6) | (b[3] & 0x3f);
- -
- - q = b3;
- - while (--i > 0)
- - putchar(*q++);
- -
- - q = b4;
- - }
- - }
- -
- - *q++ = *p++; /* the last octet */
- - ++i;
- -
- - if (last || i == 4) {
- - pack6bit(b4, i, last);
- - i = 0;
- - }
- -
- - cnt = i;
- -}
- -
- -pack6bit(p, n, last)
- - register char *p;
- - register int n;
- - int last;
- -{
- - register char *q;
- - register i = 3;
- - char b3[3];
- -
- - if (last) {
- - i = p[n-1];
- - if (i >= 3) {
- - fprintf(stderr, "Badly encoded file\n");
- - i = 3; /* do the best we can */
- - }
- - }
- -
- - q = b3;
- - *q++ = (p[0] << 2) | ((p[1] >> 4) & 0x3);
- - *q++ = (p[1] << 4) | ((p[2] >> 2) & 0xf);
- - *q = (p[2] << 6) | (p[3] & 0x3f);
- -
- - q = b3;
- -
- - while (--i >= 0)
- - putchar(*q++);
- -}
- *-*-END-of-src/decode.c-*-*
- exit
-
-